from flask import Flask, render_template, redirect, url_for, request, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from forms import LoginForm, RegisterForm, PenaltyForm, UploadForm, UserForm
from models import User, Penalty, UserRole
from extensions import db
from config import Config
import pandas as pd
from io import StringIO
from datetime import datetime
from functools import wraps

app = Flask(__name__)
app.config.from_object(Config)

# 初始化db
db.init_app(app)

login_manager = LoginManager(app)
login_manager.login_view = 'login'


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


# 管理员权限装饰器
def admin_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not current_user.is_admin():
            flash('You do not have permission to access this page.', 'danger')
            return redirect(url_for('index'))
        return f(*args, **kwargs)

    return decorated_function


@app.route('/')
@login_required
def index():
    # 获取搜索参数
    case_no = request.args.get('case_no')
    judge_date_start = request.args.get('judge_date_start')
    judge_date_end = request.args.get('judge_date_end')

    # 获取当前页码，默认为 1
    page = request.args.get('page', 1, type=int)
    per_page = 20  # 每页显示 20 条记录

    # 查询所有记录
    query = Penalty.query

    # 按案号模糊匹配
    if case_no:
        query = query.filter(Penalty.case_no.contains(case_no))

    # 按判决时间范围搜索
    if judge_date_start or judge_date_end:
        try:
            # 将字符串转换为日期对象
            if judge_date_start:
                judge_date_start = datetime.strptime(judge_date_start, '%Y-%m-%d').date()
                query = query.filter(Penalty.judge_date >= judge_date_start)
            if judge_date_end:
                judge_date_end = datetime.strptime(judge_date_end, '%Y-%m-%d').date()
                query = query.filter(Penalty.judge_date <= judge_date_end)
        except ValueError:
            flash('Invalid date format. Please use YYYY-MM-DD.', 'danger')

    # 根据角色限制数据访问
    if current_user.is_admin() or current_user.is_editor():
        penalties = query.paginate(page=page, per_page=per_page)
    else:
        # 普通用户只能查看前 20 条记录
        penalties = query.paginate(page=1, per_page=20)  # 固定为第一页，每页 20 条

    return render_template('index.html', penalties=penalties)


@app.route('/detail/<int:penalty_id>', methods=['GET', 'POST'])
@login_required
def detail(penalty_id):
    penalty = Penalty.query.get_or_404(penalty_id)
    form = PenaltyForm(obj=penalty)
    if form.validate_on_submit():
        if current_user.is_admin() or current_user.is_editor():
            form.populate_obj(penalty)
            db.session.commit()
            flash('Penalty updated successfully!', 'success')
        else:
            flash('You do not have permission to edit this record.', 'danger')
        return redirect(url_for('index'))
    return render_template('detail.html', form=form, penalty=penalty)


@app.route('/users')
@login_required
@admin_required
def user_list():
    # 获取所有用户
    users = User.query.all()
    return render_template('user_list.html', users=users)


@app.route('/user/<int:user_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def edit_user(user_id):
    # 获取用户
    user = User.query.get_or_404(user_id)
    form = UserForm(obj=user)

    if form.validate_on_submit():
        # 更新用户信息
        form.populate_obj(user)
        db.session.commit()
        flash('User updated successfully!', 'success')
        return redirect(url_for('user_list'))

    return render_template('edit_user.html', form=form, user=user)


@app.route('/user/delete/<int:user_id>', methods=['POST'])
@login_required
@admin_required
def delete_user(user_id):
    # 获取用户
    user = User.query.get_or_404(user_id)

    # 防止管理员删除自己
    if user.id == current_user.id:
        flash('You cannot delete yourself.', 'danger')
    else:
        db.session.delete(user)
        db.session.commit()
        flash('User deleted successfully!', 'success')

    return redirect(url_for('user_list'))


@app.route('/upload', methods=['GET', 'POST'])
@login_required
def upload():
    if not current_user.is_admin() and not current_user.is_editor():
        flash('You do not have permission to upload data.', 'danger')
        return redirect(url_for('index'))

    form = UploadForm()
    if form.validate_on_submit():
        file = form.file.data
        if file.filename.endswith('.xlsx') or file.filename.endswith('.xls'):
            try:
                # 读取 Excel 文件
                df = pd.read_excel(file)
                # 打印读取的数据
                print("读取的 Excel 数据：")
                print(df)

                # 处理每一行数据
                for _, row in df.iterrows():
                    data = row.to_dict()
                    # 将 NaN 转换为 None
                    for key, value in data.items():
                        if pd.isna(value):  # 检查是否为 NaN
                            data[key] = None

                    # 将 source_org_code 转换为字符串
                    if 'source_org_code' in data and pd.notna(data['source_org_code']):
                        data['source_org_code'] = str(int(data['source_org_code']))

                    penalty_id = data.get('id')
                    if penalty_id:
                        # 如果存在 id，则更新记录
                        penalty = Penalty.query.get(penalty_id)
                        if penalty:
                            print(f"更新记录：ID={penalty_id}")
                            for key, value in data.items():
                                setattr(penalty, key, value)
                    else:
                        # 如果不存在 id，则新增记录
                        print(f"新增记录：{data}")
                        penalty = Penalty(**data)
                        db.session.add(penalty)

                # 提交事务
                db.session.commit()
                flash('Data uploaded and processed successfully!', 'success')
            except Exception as e:
                db.session.rollback()
                # 打印详细的错误信息
                print(f"处理 Excel 文件时发生错误：{str(e)}")
                flash(f'Error processing file: {str(e)}', 'danger')
        else:
            flash('Invalid file format. Please upload an Excel file.', 'danger')
        return redirect(url_for('index'))
    return render_template('upload.html', form=form)


@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.password == form.password.data:
            login_user(user)
            return redirect(url_for('index'))
        else:
            flash('Login Unsuccessful. Please check username and password', 'danger')
    return render_template('login.html', form=form)


@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        user = User(username=form.username.data, password=form.password.data, role=form.role.data)
        db.session.add(user)
        db.session.commit()
        flash('Your account has been created! You are now able to log in', 'success')
        return redirect(url_for('login'))
    return render_template('register.html', form=form)


@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('login'))


if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 确保数据库表已创建
    app.run(host='0.0.0.0',debug=True)
